package org.infodavid.common.impl.persistence;

import javax.persistence.PersistenceException;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.infodavid.common.IBuilder;
import org.infodavid.common.cache.CacheUtil;
import org.infodavid.common.model.IApplicationSettings;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.persistence.ApplicationSettingsDataService;
import org.infodavid.common.persistence.PersistenceSession;
import org.infodavid.common.services.exceptions.ServiceException;

/**
 * The Class AbstractApplicationSettingsDataService.
 */
public abstract class AbstractApplicationSettingsDataService extends ApplicationSettingsDataService {

	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(AbstractApplicationSettingsDataService.class);

	/** The Constant CACHE_NAME. */
	private static final String CACHE_NAME = "ApplicationPropertiesCache";

	/** The Constant CONFIG_FILE. */
	protected static final String CONFIG_FILE = "application_properties_cache.xml";

	/** The cache of connection entries. */
	private final Cache cache;

	/** The builder. */
	private final IBuilder<IApplicationSettings> builder = ModelFactory.getInstance().getBuilder(
	    IApplicationSettings.class);

	/**
	 * The Constructor.
	 */
	protected AbstractApplicationSettingsDataService() {
		super();

		cache = CacheUtil.getInstance().buildCache(CACHE_NAME, CONFIG_FILE);
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.persistence.IDataService#create()
	 */
	public IApplicationSettings create() throws InstantiationException {
		return builder.create();
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.persistence.IDataService#copyTo(org.infodavid.common.model.IDataObject,
	 * boolean, boolean)
	 */
	public IApplicationSettings copyTo(final IApplicationSettings from, final boolean deep,
	    final boolean asNew) throws InstantiationException {
		final boolean isDebugEnabled = LOGGER.isDebugEnabled();

		if (isDebugEnabled) {
			LOGGER.debug("Copying entity from " + from + " using deep = " + deep + ", asNew = " + asNew);
		}

		final IApplicationSettings to;

		if (from == null) {
			to = null;
		}
		else {
			to = builder.create();

			copyTo(from, to, asNew);
			to.setProduct(from.getProduct());
			to.getProperties().getData().addAll(from.getProperties().getData());
		}

		if (isDebugEnabled) {
			LOGGER.debug("Copied entity = " + to);
		}

		return to;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.infodavid.common.persistence.IDataService#copyListItemTo(org.infodavid.common.model.IDataObject
	 * , boolean, boolean)
	 */
	public IApplicationSettings copyListItemTo(final IApplicationSettings from, final boolean deep,
	    final boolean asNew) throws PersistenceException, InstantiationException {
		return copyTo(from, deep, asNew);
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.infodavid.common.persistence.ApplicationSettingsDataService#findNotNullPropertyValue(com.
	 * infodavid.orgmon.persistence.PersistenceSession, java.lang.String)
	 */
	@Override
	public final String findNotNullPropertyValue(final PersistenceSession session,
	    final String property) throws PersistenceException, ServiceException {
		String result = null;

		synchronized (cache) {
			final Element elt = cache.get(property);

			if (elt == null) {
				result = doFindNotNullPropertyValue(session, property);
			}
			else {
				result = (String)elt.getObjectValue();
			}
		}

		return result;
	}

	protected abstract String doFindNotNullPropertyValue(PersistenceSession session, String property)
	    throws PersistenceException, ServiceException;
}
